package org.friping.mytool.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
import org.friping.mytool.entity.BaseEntity;
import org.friping.mytool.helper.EntityConverter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@EBean(scope = EBean.Scope.Singleton)
public class BaseDao {

    @Bean
    EntityConverter entityConverter;

    @Bean
    DaoHelper daoHelper;


    public BaseEntity get(Class clazz, Long id){
        try(SQLiteDatabase db = openDb()){
            Cursor cursor = db.query(getTableName(clazz), null, "id=?", new String[]{String.valueOf(id)}, null, null, null);
            if(cursor.moveToFirst()){
                return entityConverter.cursorToEntity(cursor, clazz);
            }
        }
        return null;
    }

    public long create(BaseEntity entity){
        try(SQLiteDatabase db = openDb()){
            return db.insert(getTableName(entity.getClass()), null, entityConverter.entityToContentValues(entity));
        }
    }

    public long create(Class<? extends BaseEntity> clazz, Map entityProps){
        try(SQLiteDatabase db = openDb()){
            return db.insert(getTableName(clazz), null, entityConverter.mapToContentValues(entityProps));
        }
    }

    public int update(BaseEntity entity, Long id){
        try(SQLiteDatabase db = openDb()){
            ContentValues contentValues = entityConverter.entityToContentValues(entity);
            contentValues.remove("id");
            return db.update(getTableName(entity.getClass()), contentValues, "id=?", new String[]{String.valueOf(id)});
        }
    }

    public long update( Class<? extends BaseEntity> clazz, Map entityProps,Long id){
        try(SQLiteDatabase db = openDb()){
            ContentValues contentValues = entityConverter.mapToContentValues(entityProps);
            contentValues.remove("id");
            return db.update(getTableName(clazz), contentValues, "id=?", new String[]{String.valueOf(id)});
        }
    }

    public long delete(Class<? extends BaseEntity> clazz, Long id){
        try(SQLiteDatabase db = openDb()){
            return db.delete(getTableName(clazz),"id=?", new String[]{String.valueOf(id)});
        }
    }

    public <T extends BaseEntity> List<T> list(Class<T> clazz){
        return list(clazz, null, null, null, null, null, null);
    }

    public <T extends BaseEntity> List<T> list(Class<T> clazz, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit){
        try(SQLiteDatabase db = openDb()){
            List results = new ArrayList();
            Cursor cursor = db.query(getTableName(clazz), null,selection, selectionArgs, groupBy,having, orderBy, limit);
            while (cursor.moveToNext()) {
                results.add(entityConverter.cursorToEntity(cursor, clazz));
            }
            return results;
        }
    }

    public <T extends BaseEntity> List<T> list(Class<T> clazz, String sql, String[] args){
        try(SQLiteDatabase db = openDb()){
            List results = new ArrayList();
            Cursor cursor = db.rawQuery(sql, args);
            while (cursor.moveToNext()) {
                results.add(entityConverter.cursorToMap(cursor, clazz));
            }
            return results;
        }
    }

    public List<? extends Map<String,?>> listWithMap(Class<? extends BaseEntity> clazz){
        return listWithMap(clazz, null, null, null, null, null, null);
    }

    public List<? extends Map<String,?>> listWithMap(Class<? extends BaseEntity> clazz, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit){
        try(SQLiteDatabase db = openDb()){
            List results = new ArrayList();
            Cursor cursor = db.query(getTableName(clazz), null,selection, selectionArgs, groupBy,having, orderBy, limit);
            while (cursor.moveToNext()) {
                results.add(entityConverter.cursorToMap(cursor, clazz));
            }
            return results;
        }
    }

    public List<? extends Map<String,String>> listWithMap(String sql, String[] args){
        try(SQLiteDatabase db = openDb()){
            List<? extends Map<String,String>> results = new ArrayList();
            Cursor cursor = db.rawQuery(sql, args);
            while (cursor.moveToNext()) {
                Map map = new HashMap();
                for(int i = 0; i < cursor.getColumnCount(); i++){
                    String column = cursor.getColumnName(i);
                    map.put(column, cursor.getString(i));
                }
            }
            return results;
        }
    }


    private String getTableName(Class<? extends BaseEntity> clazz){
        return clazz.getSimpleName().toLowerCase();
    }

    protected SQLiteDatabase openDb(){
        return daoHelper.openDb();
    }
}
